package mars.game.core;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.HashMap;
import java.util.Map;

import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.view.KeyEvent;
import android.view.MotionEvent;

public final class MarsRuntime
{
	
	public static Map<String, Bitmap> IMAGE_CACHE = new HashMap<String, Bitmap>();
	
	private static MarsRuntime instance;
	
	boolean isAppRunning;
	
	private static MarsView view;
	
	private Activity activity;
	
	long systemTime = System.currentTimeMillis();
	
	long lastFrameDuration = 0;
	
	long lastFrameStartTime = systemTime;
	
	private MarsScreen curScreen = null;
	
	public static final boolean TOGGLE_FPS = true; // 是否锁帧
	
	public static final boolean SHOW_FPS = true;
	
	public static final boolean SHOW_MEM = false;
	
	public static final int MAIN_CYCLE_TIME = 200;//原值500
	
	public int demoLimitTime = 50000;
	
	public int gcRound = -1;
	
	private Resources r;
	
	private MarsRuntime()
	{

		this.isAppRunning = true;
		
	}
	
	public static Bitmap loadBitmap(int id)
	{

//		Integer ID = new Integer(id);
		String ID = "" + id;
		if (IMAGE_CACHE.containsKey(ID))
		{
			return IMAGE_CACHE.get(ID);
//			Bitmap softReference = IMAGE_CACHE.get(ID);
//			if (softReference != null)
//			{
//				return softReference;
//			}
//			else
//			{
//				System.out.println("softReference is null");
//			return null;
//			}
		}
		else
		{
			Bitmap temp = BitmapFactory.decodeResource(getView().getResources(), id);
//			IMAGE_CACHE.put(ID, new SoftReference<Bitmap>(temp));
			IMAGE_CACHE.put(ID, temp);
			return temp;
		}
	}
	
	public void init(MarsView view,Activity activity)
	{

		this.view = view;
		this.activity = activity;
	}
	
	final void upDataTime(long roundStartTime)
	{

		systemTime = roundStartTime;
		lastFrameDuration = systemTime - lastFrameStartTime;
		lastFrameStartTime = systemTime;
	}
	
	/**
	 * Get GameRuntime instance
	 * 
	 * @return GameRuntime
	 */
	public final static MarsRuntime getRuntime()
	{

		if (instance == null)
		{
			instance = new MarsRuntime();
		}
		return instance;
	}
	
	/**
	 * Get current screen object
	 * 
	 * @return current screen
	 */
	public final MarsScreen getCurScreen()
	{

		return this.curScreen;
	}
	
	/**
	 * Change current screen
	 * 
	 * @param screen
	 *            the screen name
	 * @param entryPoint
	 *            the entry point of the screen
	 * @param args
	 *            some arguments to be passed to screen
	 */
	public final void changeScreen(MarsScreen screen, int entryPoint, Object... args)
	{

		if (this.curScreen != null)
		{
			this.curScreen.focusOut();
			this.curScreen.releaseRes();
		}
		this.curScreen = screen;
		this.curScreen.focusIn(entryPoint, args);
	}
	
	/**
	 * Get current system time
	 * 
	 * @return system time
	 */
	public final long getSystemTime()
	{

		return this.systemTime;
	}
	
	/**
	 * Get last frame duration time
	 * 
	 * @return last frame duration time
	 */
	public final long getLastFrameDuration()
	{

		return this.lastFrameDuration;
	}
	
	/**
	 * Call this method will do two things:<br>
	 * 1. set system time to current time<br>
	 * 2. set last frame duration time to 0<br>
	 * Generally, at the time the game comes back to playing state from pause,<br>
	 * you should call this method to ensure the system time is correct<br>
	 */
	public final void resetSystemTime()
	{

		this.systemTime = System.currentTimeMillis();
		this.lastFrameDuration = 0;
		this.lastFrameStartTime = this.systemTime;
	}
	
	final void input()
	{
		//触摸屏事件
		if (this.curScreen != null && currMotinEvent != null)
		{
			this.curScreen.onTouchEvent(currMotinEvent);
		}
		//按键事件
		if(this.keyDownEvent != null)
		{
			this.curScreen.onKeyDown(keyDownCode, keyDownEvent);
		}
		
		if(this.keyUpEvent != null)
		{
			this.curScreen.onKeyUp(keyUpCode, keyUpEvent);
		}
		
	}
	
	final void tick()
	{

		if (this.curScreen != null)
		{
			this.curScreen.tick();
		}
		
		eventClar();
	}
	
	private void eventClar()
	{

		currMotinEvent = null;
		keyDownCode = -1;
		keyDownEvent = null;
		keyUpCode = -1;
		keyUpEvent = null;
		
	}
	
	final void draw(Canvas c)
	{

		if (this.curScreen != null)
		{
			this.curScreen.draw(c);
		}
	}
	
	public static final int QUIT = 1;
	/**
	 * Quit MIDlet
	 */
	public void quit()
	{

		this.isAppRunning = false;
		IMAGE_CACHE = null;
		
//		Handler handler = new Handler()
//		{
//
//			@Override
//			public void handleMessage(Message msg)
//			{
//				if(msg.what == QUIT)
//				{
//					activity.finish();
//					android.os.Process.killProcess(android.os.Process.myPid());
//				}
//				// TODO Auto-generated method stub
//				super.handleMessage(msg);
//			}
//			
//		};
//		handler.hasMessages(QUIT);
		
		activity.finish();
		android.os.Process.killProcess(android.os.Process.myPid());
		// System.gc();
	}
	
	public static final MarsView getView()
	{

		if (view != null)
		{
			return view;
		}
		else
		{
			throw new IllegalStateException("MarsRuntime hasn't been initialized");
		}
	}
	
	MotionEvent currMotinEvent;
	
	public void onTouchEvent(MotionEvent event)
	{

		currMotinEvent = event;
		// TODO Auto-generated method stub
		
	}
	
	private int keyDownCode;
	private KeyEvent keyDownEvent;
	
	public void onKeyDown(int keyCode, KeyEvent event)
	{

		keyDownCode = keyCode;
		keyDownEvent = event;
		
	}
	
	private int keyUpCode;
	private KeyEvent keyUpEvent;
	
	public void onKeyUp(int keyCode, KeyEvent event)
	{

		keyUpCode = keyCode;
		keyUpEvent = event;
		
	}
	
	public FileOutputStream openOutFile()
	{
		try
		{
			return this.activity.openFileOutput("game.cfg",Context.MODE_WORLD_READABLE);
		}
		catch (FileNotFoundException e)
		{
		
			return null;
		}
	}
	
	public FileInputStream openInputFile()
	{
		try
		{
			return this.activity.openFileInput("game.cfg");
		}
		catch (FileNotFoundException e)
		{
		
			return null;
		}
	}
}